package friot.utils.tools;

import friot.utils.constants.AppHttpCodeEnum;
import friot.utils.exception.ServiceException;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * JWT工具类
 *
 * @author He Kuntao
 * @date 2023/12/1 17:02
 */
@Slf4j
public class JwtUtil {

    /**
     * SECRET
     */
    private static final String SECRET = "TESTFRSF";
    /**
     * Expire Time
     */
    private static final long EXPIRE = 1000 * 60 * 60 * 24;

    /**
     * 生成 JWT
     *
     * @param name 名称
     * @param id   User ID
     * @return JWT
     */
    public static String generateToken(String name, String id) {
        return Jwts.builder()
                // header
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")
                // payload
                .claim("name", name)
                .setId(id)
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
                // signature
                .signWith(SignatureAlgorithm.HS256, SECRET)
                .compact();
    }


    /**
     * 解析 JWT
     *
     * @param token JWT
     * @return null 解析失败，非法jwt; 非null 解析成功
     */
    public static Claims parseToken(String token) {
        try {
            return Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
        } catch (Exception e) {
            log.error("解析JWT失败", e);
            throw new ServiceException(AppHttpCodeEnum.SIGN_INVALID);
        }
    }

    /**
     * 从Req中解析token，并返回用户ID
     *
     * @param request 请求
     * @return 用户ID
     */
    public static int parseTokenToUserId(HttpServletRequest request) {
        String token = request.getHeader("token");
        if (token == null) {
            throw new ServiceException(AppHttpCodeEnum.TOKEN_REQUIRE);
        }

        try {
            Claims body = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
            return Integer.parseInt(body.getId());
        } catch (Exception e) {
            log.error("解析JWT失败", e);
            throw new ServiceException(AppHttpCodeEnum.SIGN_INVALID);
        }
    }
}
